package org.jsola.hr.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.jsola.common.ArrayKit;
import org.jsola.common.StrKit;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.ExcelKit;
import org.jsola.hr.constant.EmpSocBackStatusConstant;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IEmpSocBackRecordInfoDAO;
import org.jsola.hr.dto.EmpSocBackRecordAccountAddDTO;
import org.jsola.hr.dto.EmpSocBackRecordInfoAddDTO;
import org.jsola.hr.dto.EmpSocBackRecordInfoExportDTO;
import org.jsola.hr.dto.EmpSocBackRecordInfoUpdateDTO;
import org.jsola.hr.entity.EmpSocBackRecordAccountDO;
import org.jsola.hr.entity.EmpSocBackRecordInfoDO;
import org.jsola.hr.query.EmpSocBackRecordInfoQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.*;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 社保回款信息
 *
 * @author zhr
 */
@Service("hrEmpSocBackRecordInfoServiceImpl")
public class EmpSocBackRecordInfoServiceImpl implements IEmpSocBackRecordInfoService {

    @Autowired
    private IEmpSocBackRecordInfoDAO empSocBackRecordInfoDAO;
    @Autowired
    private IEmpSocBackRecordAccountService empSocBackRecordAccountService;
    @Autowired
    private IEmpInfoService empInfoService;
    @Autowired
    private IEmpSocBackRecordRecordService empSocBackRecordRecordService;
    @Autowired
    private ICompanyService companyService;

    private final Map<Integer, String> wayStatusToString = new HashMap<Integer, String>(8) {{
        put(1, "银行");
        put(2, "微信");
        put(3, "支付宝");
        put(4, "其他");
        put(5, "余额扣款");
    }};

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpSocBackRecordInfoVO save(EmpSocBackRecordInfoAddDTO empSocBackRecordInfoAddDTO, TokenUser tokenUser) {
        if (empSocBackRecordInfoAddDTO.getServiceCost() == null) {
            empSocBackRecordInfoAddDTO.setServiceCost(new BigDecimal("0"));
        }
        if (empSocBackRecordInfoAddDTO.getSocAmount() == null) {
            empSocBackRecordInfoAddDTO.setSocAmount(new BigDecimal("0"));
        }
        if (empSocBackRecordInfoAddDTO.getOverdueFine() == null) {
            empSocBackRecordInfoAddDTO.setOverdueFine(new BigDecimal("0"));
        }
        // 校验员工id是否正确
        EmpInfoVO empInfoVO = empInfoService.selectById(empSocBackRecordInfoAddDTO.getEmpId(), tokenUser.getSiteId());
        ParamException.notNull(empInfoVO, "员工id不正确或该员工已被删除，请刷新后重试");
        // 判断是否重复添加
        Example example = new Example(EmpSocBackRecordInfoDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("year", empSocBackRecordInfoAddDTO.getYear())
                .andEqualTo("month", empSocBackRecordInfoAddDTO.getMonth())
                .andEqualTo("empId", empSocBackRecordInfoAddDTO.getEmpId())
                .andEqualTo("siteId", tokenUser.getSiteId());
        List<EmpSocBackRecordInfoDO> empSocBackRecordInfoDOList = empSocBackRecordInfoDAO
                .selectByExample(example);
        ParamException.isTrue(CollectionUtils.isEmpty(empSocBackRecordInfoDOList),
                empInfoVO.getName() + "对应的参保记录已有回款信息，刷新或删除后重试!");
        // 转DO 并设置初始值
        EmpSocBackRecordInfoDO empSocBackRecordInfoDO = empSocBackRecordInfoAddDTO.to(EmpSocBackRecordInfoDO.class);
        empSocBackRecordInfoDO.setRealityAmount(new BigDecimal("0"));
        empSocBackRecordInfoDO.setStatus(EmpSocBackStatusConstant.STATUS_ONE);
        empSocBackRecordInfoDO.setTotalAmount(empSocBackRecordInfoDO.getSocAmount()
                .add(empSocBackRecordInfoDO.getServiceCost()).add(empSocBackRecordInfoDO.getOverdueFine()));
        empSocBackRecordInfoDO.setName(empInfoVO.getName());
        empSocBackRecordInfoDO.setPhone(empInfoVO.getPhone());
        empSocBackRecordInfoDO.setIdCard(empInfoVO.getIdCard());
        empSocBackRecordInfoDO.setUncollectedAmount(empSocBackRecordInfoDO.getSocAmount()
                .add(empSocBackRecordInfoDO.getServiceCost()).add(empSocBackRecordInfoDO.getOverdueFine()));
        // 保存
        empSocBackRecordInfoDO = save(empSocBackRecordInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
        // 根据该员工id查询是否有账户信息
        EmpSocBackRecordAccountDO empSocBackRecordAccountDO = empSocBackRecordAccountService
                .selectDOByEmpId(empInfoVO.getId(), tokenUser.getSiteId());
        if (Objects.isNull(empSocBackRecordAccountDO)) {
            // 新增该员工账户
            EmpSocBackRecordAccountAddDTO empSocBackRecordAccountAddDTO = new EmpSocBackRecordAccountAddDTO();
            empSocBackRecordAccountAddDTO.setEmpId(empInfoVO.getId());
            empSocBackRecordAccountAddDTO.setAmount(new BigDecimal("0"));
            empSocBackRecordAccountService.save(empSocBackRecordAccountAddDTO, tokenUser);
        }
        return empSocBackRecordInfoDO.to(EmpSocBackRecordInfoVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer saveBatch(EmpSocBackRecordInfoAddDTO[] empSocBackRecordInfos, TokenUser tokenUser) {
        for (EmpSocBackRecordInfoAddDTO empSocBackRecordInfo : empSocBackRecordInfos) {
            this.save(empSocBackRecordInfo, tokenUser);
        }
        return empSocBackRecordInfos.length;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(EmpSocBackRecordInfoUpdateDTO empSocBackRecordInfoUpdateDTO, TokenUser tokenUser) {
        //转DO
        EmpSocBackRecordInfoDO empSocBackRecordInfoDO = empSocBackRecordInfoUpdateDTO.to(EmpSocBackRecordInfoDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(empSocBackRecordInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... empSocBackRecordInfoIds) {
        for (String empSocBackRecordInfoId : empSocBackRecordInfoIds) {
            EmpSocBackRecordInfoDO empSocBackRecordInfoDO = this
                    .selectDOById(empSocBackRecordInfoId, tokenUser.getSiteId());
            ParamException.notNull(empSocBackRecordInfoDO, "根据id查询为空，请刷新重试或联系管理员");
            // 删除这条信息对应的回款记录(根据empId、年、月)
            List<EmpSocBackRecordRecordVO> empSocBackRecordRecordList = empSocBackRecordRecordService
                    .selectByEmpIdAndYearAndMonth(empSocBackRecordInfoDO.getEmpId(), empSocBackRecordInfoDO.getYear()
                            , empSocBackRecordInfoDO.getMonth(), tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(empSocBackRecordRecordList)) {
                for (EmpSocBackRecordRecordVO empSocBackRecordRecord : empSocBackRecordRecordList) {
                    empSocBackRecordRecordService.deleteByIds(tokenUser, empSocBackRecordRecord.getId());
                }
            }
        }
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) empSocBackRecordInfoIds);
    }


    @Override
    public EmpSocBackRecordInfoVO selectById(String empSocBackRecordInfoId, String siteId) {
        EmpSocBackRecordInfoDO empSocBackRecordInfoDO = selectDOById(empSocBackRecordInfoId, siteId);
        if (empSocBackRecordInfoDO == null) {
            return null;
        }
        return empSocBackRecordInfoDO.to(EmpSocBackRecordInfoVO.class);
    }

    @Override
    public List<EmpSocBackRecordInfoListVO> select(EmpSocBackRecordInfoQuery empSocBackRecordInfoQuery, String siteId) {
        List<EmpSocBackRecordInfoDO> empSocBackRecordInfoDOList = selectDO(empSocBackRecordInfoQuery, siteId);
        if (CollectionUtils.isEmpty(empSocBackRecordInfoDOList)) {
            return empSocBackRecordInfoDOList == null ? null : new ArrayList<>();
        }
        return empSocBackRecordInfoDOList.stream()
                .map(empSocBackRecordInfoDO -> empSocBackRecordInfoDO.to(EmpSocBackRecordInfoListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(EmpSocBackRecordInfoQuery empSocBackRecordInfoQuery, String siteId) {
        Example example = buildExample(empSocBackRecordInfoQuery, siteId);
        return empSocBackRecordInfoDAO.selectCountByExample(example);
    }

    @Override
    public Page<EmpSocBackRecordInfoListVO> selectPage(EmpSocBackRecordInfoQuery query, String siteId) {
        ParamException.notNull(query.getCompanyIds(), "请选择查询的用工单位或用工单位分组");
        query.setCompanyIdList(ArrayKit.split(query.getCompanyIds(), ","));
        if (ObjectUtils.isEmpty(query.getSurplusAmountMax())) {
            query.setSurplusAmountMax(new BigDecimal("10000000"));
        }
        if (ObjectUtils.isEmpty(query.getSurplusAmountMin())) {
            query.setSurplusAmountMin(new BigDecimal("0"));
        }
        PageInfo<EmpSocBackRecordInfoListVO> resultPageInfo = PageHelper.startPage(query.getPageNo(),
                query.getPageSize()).doSelectPageInfo(() -> selectBackRecordInfo(query, siteId));
        return new Page<>(resultPageInfo.getList(), resultPageInfo.getPageNum(), resultPageInfo.getPageSize(),
                (int) resultPageInfo.getTotal());
    }

    @Override
    public EmpSocBackRecordInfoDO selectDOById(String empSocBackRecordInfoId, String siteId) {
        return listById(empSocBackRecordInfoId, siteId);
    }

    @Override
    public List<EmpSocBackRecordInfoDO> selectDO(EmpSocBackRecordInfoQuery empSocBackRecordInfoQuery, String siteId) {
        Example example = buildExample(empSocBackRecordInfoQuery, siteId);
        return empSocBackRecordInfoDAO.selectByExample(example);
    }

    @Override
    public List<EmpSocBackRecordInfoListVO> selectBackRecordInfo(EmpSocBackRecordInfoQuery query, String siteId) {
        return empSocBackRecordInfoDAO.selectSocBackPage(query, siteId);
    }

    @Override
    public String selectExportPath(EmpSocBackRecordInfoQuery query, String siteId) {
        List<EmpSocBackRecordInfoListVO> exportInfoList = selectBackRecordInfo(query, siteId);
        //需要合并的列
        int[] mergeColumnIndex = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        // 从那一行开始合并
        int mergeRowIndex = 1;
        List<EmpSocBackRecordInfoExportDTO> exportList = new ArrayList<>();
        for (EmpSocBackRecordInfoListVO empSocBackRecordInfo : exportInfoList) {
            List<EmpSocBackRecordRecordVO> empBackRecordList = empSocBackRecordRecordService
                    .selectByEmpIdAndYearAndMonth(empSocBackRecordInfo.getEmpId(), empSocBackRecordInfo.getYear(),
                            empSocBackRecordInfo.getMonth(), siteId);
            if (CollectionUtils.isEmpty(empBackRecordList)) {
                EmpSocBackRecordInfoExportDTO export = empSocBackRecordInfo.to(EmpSocBackRecordInfoExportDTO.class);
                export.setResponsibleName(empSocBackRecordInfo.getEmpResponsibleName());
                exportList.add(export);
            } else {
                for (EmpSocBackRecordRecordVO record : empBackRecordList) {
                    EmpSocBackRecordInfoExportDTO exportInfo = empSocBackRecordInfo.to(EmpSocBackRecordInfoExportDTO.class);
                    exportInfo.setWayStatus(record.getWayStatus());
                    exportInfo.setInfoRealityAmount(record.getRealityAmount());
                    exportInfo.setOperateUser(record.getCreateUserName());
                    exportInfo.setOperateDate(record.getGmtCreate());
                    exportInfo.setAmount(record.getAmount());
                    exportInfo.setResponsibleName(empSocBackRecordInfo.getEmpResponsibleName());
                    exportList.add(exportInfo);
                }
            }
        }
        return ExcelKit.exportExcelMerge("socBack", "回款记录",
                EmpSocBackRecordInfoExportDTO.class, exportList, mergeRowIndex, mergeColumnIndex);
    }

    @Override
    public void setEmpInfoToEmpSocBackRecordInfo(EmpSocBackRecordInfoListVO empSocBackRecordInfoListVO, TokenUser tokenUser) {
        // 查询账户信息
        EmpSocBackRecordAccountDO empSocBackRecordAccountDO = empSocBackRecordAccountService
                .selectDOByEmpId(empSocBackRecordInfoListVO.getEmpId(), tokenUser.getSiteId());
        if (Objects.nonNull(empSocBackRecordAccountDO)) {
            empSocBackRecordInfoListVO.setRemainAmount(empSocBackRecordAccountDO.getAmount());
        }
        // 查询员工信息
        EmpInfoVO empInfoVO = empInfoService
                .selectById(empSocBackRecordInfoListVO.getEmpId(), tokenUser.getSiteId());
        if (Objects.isNull(empInfoVO)) {
            empSocBackRecordInfoListVO.setRemark("此人在花名册中已被删除！");
            EmpInfoListVO empInfoListVO = new EmpInfoListVO();
            empInfoListVO.setName("此人在花名册中已被删除！");
            empSocBackRecordInfoListVO.setEmpInfoVO(empInfoListVO);
            empSocBackRecordInfoListVO.setName("此人在花名册中已被删除！");
        } else {
            empSocBackRecordInfoListVO.setRemark(empInfoVO.getRemark());
            EmpInfoListVO empInfoListVO = empInfoVO.to(EmpInfoListVO.class);
            empInfoService.otherHeaderAssignment(empInfoListVO, tokenUser);
            // 员工与部门的关系
            Map<String, List<EmpReduceInfoVO>> empDepMap = empInfoService
                    .getEmpDepMap(empSocBackRecordInfoListVO.getCompanyId(), tokenUser.getSiteId());
            // 员工与岗位的关系
            Map<String, List<EmpReduceInfoVO>> empPositionMap = empInfoService
                    .getEmpPositionMap(empSocBackRecordInfoListVO.getCompanyId(), tokenUser.getSiteId());
            // 部门
            String depNames = empInfoService.getDepNameByEmpId(empInfoListVO.getId(), empDepMap);
            if (StringUtils.isEmpty(depNames)) {
                empInfoListVO.setDepName("暂无");
            } else {
                empInfoListVO.setDepName(depNames);
            }
            // 岗位
            String positionNames = empInfoService.getPositionNameByEmpId(empInfoListVO.getId(), empPositionMap);
            if (StringUtils.isEmpty(positionNames)) {
                empInfoListVO.setPositionName("暂无");
            } else {
                empInfoListVO.setPositionName(positionNames);
            }
            empSocBackRecordInfoListVO.setEmpInfoVO(empInfoListVO);
            // 应收
            BigDecimal totalAmount = empSocBackRecordInfoListVO.getTotalAmount();
            // 回款实收
            BigDecimal realityAmount = empSocBackRecordInfoListVO.getRealityAmount() == null ?
                    new BigDecimal("0") : empSocBackRecordInfoListVO.getRealityAmount();
            // 余额累计扣款
            BigDecimal accountAmount = empSocBackRecordInfoListVO.getAccountAmount() == null ?
                    new BigDecimal("0") : empSocBackRecordInfoListVO.getAccountAmount();
            // 计算未回款金额
            BigDecimal surplusAmount = totalAmount.subtract(realityAmount).subtract(accountAmount);
            if (surplusAmount.compareTo(new BigDecimal(0)) < 0) {
                empSocBackRecordInfoListVO.setSurplusAmount(new BigDecimal("0"));
            } else {
                empSocBackRecordInfoListVO.setSurplusAmount(surplusAmount);
            }
            // 查询公司名称
            if (StrKit.isNotEmpty(empSocBackRecordInfoListVO.getCompanyId())) {
                CompanyVO companyVO = companyService
                        .selectBaseCompanyById(empSocBackRecordInfoListVO.getCompanyId(), tokenUser.getSiteId());
                if (Objects.nonNull(companyVO)) {
                    empSocBackRecordInfoListVO.setCompanyName(companyVO.getName());
                }

            }
        }


    }

    @Override
    public EmpSocBackRecordInfoDO selectByEmpIdAndYearAndMonth(String empId, String year,
                                                               String month, TokenUser tokenUser) {
        if (StrKit.isEmpty(empId) || StrKit.isEmpty(year) || StrKit.isEmpty(month)) {
            throw new ParamException("empId、year、month都不能为空");
        }
        Example example = new Example(EmpSocBackRecordInfoDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("empId", empId)
                .andEqualTo("year", year)
                .andEqualTo("month", month);
        List<EmpSocBackRecordInfoDO> empSocBackRecordInfoDOList = empSocBackRecordInfoDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empSocBackRecordInfoDOList)) {
            return null;
        }
        return empSocBackRecordInfoDOList.get(0);
    }


    /**
     * 根据查询参数，构建example
     *
     * @param empSocBackRecordInfoQuery 查询参数
     * @param siteId                    所属站点id
     * @return example
     */
    private Example buildExample(EmpSocBackRecordInfoQuery empSocBackRecordInfoQuery, String siteId) {
        Example example = new Example(EmpSocBackRecordInfoDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (empSocBackRecordInfoQuery.getEmpSocInfoId() != null) {
            example.and().andEqualTo("empSocInfoId", empSocBackRecordInfoQuery.getEmpSocInfoId());
        }
        if (empSocBackRecordInfoQuery.getEmpId() != null) {
            example.and().andEqualTo("empId", empSocBackRecordInfoQuery.getEmpId());
        }
        if (empSocBackRecordInfoQuery.getYear() != null) {
            example.and().andEqualTo("year", empSocBackRecordInfoQuery.getYear());
        }
        if (empSocBackRecordInfoQuery.getMonth() != null) {
            example.and().andEqualTo("month", empSocBackRecordInfoQuery.getMonth());
        }
        if (empSocBackRecordInfoQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", empSocBackRecordInfoQuery.getCompanyId());
        }
        if (StrKit.isNotEmpty(empSocBackRecordInfoQuery.getCompanyIds())) {
            List<String> companyIds = ArrayKit.split(empSocBackRecordInfoQuery.getCompanyIds(), ",");
            example.and().andIn("companyId", companyIds);
        }
        if (empSocBackRecordInfoQuery.getStatus() != null) {
            example.and().andEqualTo("status", empSocBackRecordInfoQuery.getStatus());
        }
        // 排序
        ExampleKit.setExampleOrder(example, empSocBackRecordInfoQuery.getOrders());
        return example;
    }
}




